import LXCOM from '../common/common.js'
import baseunitgrah from './baseunitgrah.js'
import { CoordTRFUtil } from '../common/tools/coordtool.js'
import Coord from '../common/struct/coord.js'
import ActPkg from '../graph/action/circleaction.js'
import UtilFuncs from '../common/tools/utilfuncs.js'
var funcs = UtilFuncs.UtilFuncs;

import GlobalConst from '../common/globalConst.js'
var global = GlobalConst.GlobalConst;
import {FillUtil} from '../graph/paintutil/fillutil.js'
import {Strokeutil} from '../graph/paintutil/strokeutil.js'

import {LGXEnums}  from '../common/sysenum.js'


import { CommonPaintUtil } from './paintutil/compaintutil.js'
import { GlobalVar } from '../common/globalvar.js'

import circle from '../common/struct/basestruct/circle.js'
var circleUnit = circle.Circle;


class CircleGraph extends baseunitgrah.BaseUnitGraph {
    constructor(type) {
        super(type);
        this.m_graphType = LGXEnums.LGXGraphType.CircleGraph_type;
        var p = new Coord.CirclePos();
        this.setPos(p);
        var action = new ActPkg.CircleGraphAction(this);
        this.setActionSvc(action);
        this.buterflyColor = [];
    }

    display(map, mapInfo,forClip) {
        var postion = this.getPos();
        var lenthDisScale = mapInfo.getLenthDisScale();
        var disRadius = postion.radius*lenthDisScale;
        var x = postion.x;
        var y = postion.y;
        var cntpt = { x, y };
        var p1 = CoordTRFUtil.world2Screen(cntpt, mapInfo);

        var cntWorldPT = this.getZone().getCnt();
        var cntScreenPT = CoordTRFUtil.world2Screen(cntWorldPT, mapInfo);
        let rotv = this.getRadAngle();

        map.save();
        map.translate(cntScreenPT.x, cntScreenPT.y);
        map.rotate(-rotv);
        map.scale(this.localScale.x,this.localScale.y);
        map.translate(-cntScreenPT.x, -cntScreenPT.y);
        map.beginPath();
        map.ellipse(p1.x, p1.y, disRadius, disRadius, 0, 0, Math.PI * 2, false);
        map.closePath();
        
        if (!forClip){
            Strokeutil.active(this._lineDef, this, map, mapInfo);
            FillUtil.active(this._fillDef, map, this, mapInfo, false);
        }
        map.restore();

        super.displayGraphScope(map, mapInfo);
        this.displayFeaturePoint(map, mapInfo);
        if (this._highLight){
            CommonPaintUtil.disPointCross(cntpt,GlobalVar.highlightColor.toHexString(),map,mapInfo);
        }
    }

    displayButerfly(map, cntScreenPT, disRadius, mapInfo) {
        map.translate(cntScreenPT.x, cntScreenPT.y);
        console.log("displayButerfly-----------------------");
        let firstFlag = false;
        if (this.buterflyColor.length == 0) {
            firstFlag = true;
        }
        let idx = 0;
        for (let n = 3; n < 200; n += 2) {
            let ptlst = [];
            for (let i = 0; i < 360; i++) {
                let theta = i * Math.PI / 180;
                let x = Math.cos(theta) * (Math.exp(Math.cos(theta)) - 2 * Math.cos(4 * theta) + Math.pow(Math.sin(theta / 12), 5))
                let y = Math.sin(theta) * (Math.exp(Math.cos(theta)) - 2 * Math.cos(4 * theta) + Math.pow(Math.sin(theta / 12), 5))
                ptlst.push({ x, y });
            }

            map.beginPath();
            let radius = disRadius * n / 200;
            let p0 = ptlst[0];
            map.moveTo(p0.x * radius, p0.y * radius);
            for (let i = 1; i < ptlst.length; i++) {
                let pt = ptlst[i];
                map.lineTo(pt.x * radius, pt.y * radius);
            }
            map.closePath();
            let color = null;
            if (firstFlag) {
                let r = parseInt(Math.random() * 255);
                let g = parseInt(Math.random() * 255);
                let b = parseInt(Math.random() * 255);
                color = new LXCOM.LGXColor();
                color.setVal(r, g, b);
                this.buterflyColor.push(color);
            }
            else {
                color = this.buterflyColor[idx]
            }

            map.strokeStyle = color.toHexString();
            map.stroke();
            idx++;
        }
    }

    displayFeaturePoint(map, mapInfo) {
        if (mapInfo.paintForGenerateICON) {
            return;
        }

        if (this._selected) {
            super.displayFeaturePoint(map, mapInfo);
        }
        else if (this.m_pContainer && this.m_pContainer._selected) {
            this.displayControlPoint(map, mapInfo);
        }
    }

    disInSymbol(transformInfo,map, mapInfo,forClip) {
        var postion = this.getPos();
        var lenthDisScale = mapInfo.getLenthDisScale();
        var disRadius = postion.radius*lenthDisScale*transformInfo.sx;
        let scrnCnt = this.convertLocalPt2Screen(postion,mapInfo,transformInfo);
        map.save();
        map.beginPath();
        map.arc(scrnCnt.x, scrnCnt.y, disRadius, 0, 2 * Math.PI);
        map.closePath();
        if (!forClip){
            Strokeutil.active(this._lineDef, this, map, mapInfo);
            FillUtil.active(this._fillDef, map, this, mapInfo, true,transformInfo);
        }
        map.restore();
    }

    distance(tPoint, scaling, mapscale) {
        if (!super.preCheckInScope(tPoint, scaling)) {
            return -1;
        }
        var cmpGap = super.getSelCmpGap(scaling, mapscale);
        var dis = 0;
        var postion = this.getPos();
        var x = postion.x;
        var y = postion.y;
        var pt = { x, y };//圆心
        var pt2CntDis = funcs.distancePoint(pt, tPoint, 1);
        var disGap = Math.abs(pt2CntDis - postion.radius) * scaling;
        if (disGap <= cmpGap) {
            // dis = disGap;
            dis = 0;
        }
        else {
            dis = pt2CntDis;
            if (dis < postion.radius && this._fillDef.fillStyle != LGXEnums.LGXFillStyle.EMPTY){
                dis = 0
            }
            else{
                dis = -1;
            }
        }
        // if (!GlobalVar.easySelMode && dis > cmpGap){
        //     dis = -1;
        // }
        return dis;
    }

    calculateSubKind(tPoint, scaling, mapscale) {
        var nRefKind = 0;
        var cmpGap = super.getSelCmpGap(scaling, mapscale);

        var ptlst = this.getFeaturePtLst();
        //先检查当前鼠标位置是否足够临近特征点
        for (var i = 0; i < ptlst.length; i++) {
            var pt = ptlst[i];
            var lRst = funcs.distancePoint(pt, tPoint, scaling);
            if ((lRst <= cmpGap) && (lRst >= 0)) {
                nRefKind = i + 1;
                tPoint.clone(pt);
            }
        }

        if (nRefKind != 0) {
            return nRefKind;
        }

        let dis = funcs.distancePoint(tPoint,this._position,1);
        if (this._fillDef.fillStyle != LGXEnums.LGXFillStyle.EMPTY){
            //填充的，只要选中圆内即可
            if (dis < this._position.radius) {
                nRefKind = 10;
            }
        }
        else{
            //不填充的则要选中圆上
            if (Math.abs(dis - this._position.radius)*scaling  < cmpGap) {
                nRefKind = 10;
            }
        }
        return nRefKind;
    }

    calculateSubControlPoint(tPoint, scaling, mapscale) {
        let nRefKind = 0;
        let cmpGap = global.FocusSelGap;
        let ptlst = this.getControlPtLst();
        for (let i = 0; i < ptlst.length; i++) {
            let ctrlPt = ptlst[i];
            let dis = funcs.distancePoint({ x: ctrlPt.x, y: ctrlPt.y }, tPoint, scaling);
            if ((dis <= cmpGap) && (dis >= 0)) {
                nRefKind = LGXEnums.LGXModGraphKind.CommonStSelKind + ctrlPt.kind;
                tPoint.clone(ctrlPt);
            }
        }

        return nRefKind;
    }

    displayControlPoint(map, mapInfo) {
        let ptlst = this.getControlPtLst();
        for (let i = 0; i < ptlst.length; i++) {
            let ctrlPt = ptlst[i];
            var pt = CoordTRFUtil.world2Screen(ctrlPt, mapInfo);
            super.drawFocusPoint(map, pt.x, pt.y, "#ff00ff");
        }
    }

    calScope(mapscale) {
        var postion = this.getPos();
        this._zone.left = (postion.x - postion.radius);
        this._zone.bottom = (postion.y - postion.radius);
        this._zone.right = (postion.x + postion.radius);
        this._zone.top = (postion.y + postion.radius);
    }

    getLocalZone() {
        let rect = new LXCOM.LGXRect(0, 0, 0, 0);
        var postion = this.getPos();
        rect.left = (- postion.radius);
        rect.bottom = (- postion.radius);
        rect.right = (postion.radius);
        rect.top = (postion.radius);
        return rect;
    }

    getFeaturePtLst() {
        var postion = this.getPos();
        var ptlst = new Array;

        var p = new LXCOM.LGXPoint();
        p.x = postion.x;
        p.y = postion.y - postion.radius;
        ptlst.push(p);

        p = new LXCOM.LGXPoint();
        p.x = postion.x - postion.radius;
        p.y = postion.y;
        ptlst.push(p);

        p = new LXCOM.LGXPoint();
        p.x = postion.x + postion.radius;
        p.y = postion.y;
        ptlst.push(p);

        p = new LXCOM.LGXPoint();
        p.x = postion.x;
        p.y = postion.y + postion.radius;
        ptlst.push(p);

        p = new LXCOM.LGXPoint();
        p.x = postion.x;
        p.y = postion.y;
        ptlst.push(p);
        return ptlst;
    }

//     LGXEnums.LGXModGraphKind.Drag_TopMid = 5005;
// LGXEnums.LGXModGraphKind.Drag_RightMid = 5006;
// LGXEnums.LGXModGraphKind.Drag_BottomMid = 5007;
// LGXEnums.LGXModGraphKind.Drag_LeftMid = 5008;

    getControlPtLst() {
        var postion = this.getPos();
        var ptlst = new Array;

        let x = 0;
        let y = 0;

        x = postion.x;
        y = postion.y + postion.radius;
        let ctrlPt = { kind: 5, x, y };
        ptlst.push(ctrlPt);

        x = postion.x + postion.radius;
        y = postion.y;
        ctrlPt = { kind: 6, x, y };
        ptlst.push(ctrlPt);

        x = postion.x;
        y = postion.y - postion.radius;
        ctrlPt = { kind: 7, x, y };
        ptlst.push(ctrlPt);

        x = postion.x - postion.radius;
        y = postion.y;
        ctrlPt = { kind: 8, x, y };
        ptlst.push(ctrlPt);
        
        return ptlst;
    }

    getDimDatumFeatureLst() {
        let rstArr = [];

        let idkey = 1;

        let position = this.getPos();
        //图形中心
        {
            let data = { x: position.x, y: position.y };
            let info = { type: LGXEnums.DimDatumType.center, data,id:idkey++ };
            rstArr.push(info);
        }

        let idxVal = 0;
        //顶点特征
        let x = position.x;
        let y = position.y + position.radius;
        let data = {idx:idxVal++,x,y};
        let info = { type: LGXEnums.DimDatumType.vertex, data,id:idkey++ };
        rstArr.push(info);

        x = position.x + position.radius;
        y = position.y;
        data = {idx:idxVal++,x,y};
        info = { type: LGXEnums.DimDatumType.vertex, data,id:idkey++  };
        rstArr.push(info);

        x = position.x;
        y = position.y - position.radius;
        data = {idx:idxVal++,x,y};
        info = { type: LGXEnums.DimDatumType.vertex, data,id:idkey++  };
        rstArr.push(info);

        x = position.x - position.radius;
        y = position.y;
        data = {idx:idxVal++,x,y};
        info = { type: LGXEnums.DimDatumType.vertex, data,id:idkey++  };
        rstArr.push(info);
        return rstArr;
    }

    movePosOffset(tOffset, modCmdInfo) {
        if (this._selKind < 1) {
            return;
        }
        var nRefKind = this._selKind;
        var pCirclePos = this.getPos();

        if (nRefKind > 0 && nRefKind < 5) {
            var selPos = new LXCOM.LGXPoint();
            if (nRefKind == 1) {
                selPos.x = pCirclePos.x;
                selPos.y = pCirclePos.y - pCirclePos.radius;
            }
            else if (nRefKind == 2) {
                selPos.x = pCirclePos.x - pCirclePos.radius;
                selPos.y = pCirclePos.y;
            }
            else if (nRefKind == 3) {
                selPos.x = pCirclePos.x + pCirclePos.radius;
                selPos.y = pCirclePos.y;
            }
            else if (nRefKind == 4) {
                selPos.x = pCirclePos.x;
                selPos.y = pCirclePos.y + pCirclePos.radius;
            }

            var nNewRefPosX = (selPos.x + tOffset.x);
            var nNewRefPosY = (selPos.y + tOffset.y);
            this.distortModify(nNewRefPosX, nNewRefPosY);

            selPos.x += tOffset.x;
            selPos.y += tOffset.y;
        }
        else {
            this.translate(tOffset, modCmdInfo.mapscale,false);
        }
    }

    distortModify(nNewRefPosX, nNewRefPosY) {
        var pCirclePos = this.getPos();
        switch (this._selKind) {
            case 1:
            case 4:
                pCirclePos.radius = Math.abs(nNewRefPosY - pCirclePos.y);
                break;

            case 2:
            case 3:
                pCirclePos.radius = Math.abs(nNewRefPosX - pCirclePos.x);
                break;

            default:
                break;
        }
    }

    getMainFeaturePTLst(tFeaturePTLst,transformInfo) {
        var postion = this.getPosCopy();
        var p = new LXCOM.LGXPoint();
        p.x = postion.x;
        p.y = postion.y - postion.radius;
        let featurePT = this.convertPt2World(p,transformInfo);
        tFeaturePTLst.push({pt:featurePT,kind:LGXEnums.AuxPointKind.end});

        p = new LXCOM.LGXPoint();
        p.x = postion.x - postion.radius;
        p.y = postion.y;
        featurePT = this.convertPt2World(p,transformInfo);
        tFeaturePTLst.push({pt:featurePT,kind:LGXEnums.AuxPointKind.end});

        p = new LXCOM.LGXPoint();
        p.x = postion.x + postion.radius;
        p.y = postion.y;
        featurePT = this.convertPt2World(p,transformInfo);
        tFeaturePTLst.push({pt:featurePT,kind:LGXEnums.AuxPointKind.end});

        p = new LXCOM.LGXPoint();
        p.x = postion.x;
        p.y = postion.y + postion.radius;
        featurePT = this.convertPt2World(p,transformInfo);
        tFeaturePTLst.push({pt:featurePT,kind:LGXEnums.AuxPointKind.end});

        p = new LXCOM.LGXPoint();
        p.x = postion.x;
        p.y = postion.y;
        featurePT = this.convertPt2World(p,transformInfo);
        tFeaturePTLst.push({pt:featurePT,kind:LGXEnums.AuxPointKind.center});
        return ;
    }

    getSubFeaturePTLst(tFeaturePTLst,mousePoint,transformInfo) {
        let position = this.getPosCopy();
        let tmpCnt = this.convertPt2World(position,transformInfo);
        position.x = tmpCnt.x;
        position.y = tmpCnt.y;
        let interPtList = funcs.getLineInterCircle(mousePoint,tmpCnt,position);
        if (!interPtList || (interPtList && interPtList.length == 0)){
            return ;
        }

        if (interPtList.length == 1){
            let pt = interPtList[0];
            tFeaturePTLst.push({pt,kind:LGXEnums.AuxPointKind.commonPt});
        }
        else if (interPtList.length == 2){
            let pt0 = interPtList[0];
            let pt1 = interPtList[1];
            let dis0 = funcs.distancePoint(pt0,mousePoint,1);
            let dis1 = funcs.distancePoint(pt1,mousePoint,1);
            let dstPt = pt0;
            if (dis1 < dis0){
                dstPt = pt1;
            }
            tFeaturePTLst.push({pt:dstPt,kind:LGXEnums.AuxPointKind.commonPt});
        }
    }

    assignInfo(info) {
        super.assignInfo(info);
    }

    modifyAttribute(info, mapscale) {
        super.modifyAttribute(info,mapscale);
        this.calScope(mapscale);
    }

    toInfo() {
        var info = new circleUnit();
        this.toInfo4InheritClass(info);
        info.radius = this._position.radius;
        info.x = this._position.x;
        info.y = this._position.y;
        return info;
    }

    modifyCoord(propName, propVal, mapscale) {
        var position = this.getPos();
        if (propName == "cnt") {
            position.x = parseFloat(propVal.x);
            position.y = parseFloat(propVal.y);
        }
        else if (propName == "radius") {
            position.radius = parseFloat(propVal);
        }
        this.notifyToObserver();
        this.calScope(mapscale);
    }

    getCoordInfo() {
        let graphPropDef = this.getCoordPropDef();
        let tableData = [];
        var position = this.getPos();
        let x = position.x;
        let y = position.y;
        let cntObj = {
            propName: 'cnt',
            propLabel: '圆心',
            propValue: { x, y }
        };
        tableData.push(cntObj);

        let radisObj = {
            propName: 'radius',
            propLabel: '短轴',
            propValue: position.radius
        };
        tableData.push(radisObj);

        let tableForm = {
            'tableData': tableData
        };
        return { graphPropDef, tableForm };
    }

    getCoordPropDef() {
        let graphPropDef = {
            cnt: {
                vtype: global.Pt_CoordType,
                range: { min: 1, max: 300 },
            },
            radius: {
                vtype: global.Single_CoordType,
                range: { min: 1, max: 300 },
            }
        }
        return graphPropDef;
    }

    getPosCopy() {
        let pos = new Coord.CirclePos();
        pos.clone(this._position);
        return pos;
    }

    onChgDimValue(dimGraph,oldValue,newValue){
        console.log("rect graph onChgDimValue******");
        let svc = new CircleDimChg(this);
        svc.onChgDimValue(dimGraph,oldValue,newValue);
    }

    onDimBaseChged(dimGraph){
        console.log("rect onDimBaseChged******");
        let svc = new CircleDimBaseChange(this);
        svc.onBaseChanged(dimGraph);
    }

    getLocalOrigin(){
        let pt = {x:0,y:0};
        pt.x = this._position.x;
        pt.y = this._position.y;
        return pt;
    }

    clipFillZone_ex(map,mapInfo,transformInfo){
        map.clip();
        var postion = this.getPosCopy();
        var scaling = mapInfo.getScaling();
        var disRadius = scaling * postion.radius;
        var p1 = CoordTRFUtil.world2Screen(postion, mapInfo);

        var cntWorldPT = this.getZone().getCnt();
        var cntScreenPT = CoordTRFUtil.world2Screen(cntWorldPT, mapInfo);
        let rotv = this.getRadAngle();

        map.translate(cntScreenPT.x, cntScreenPT.y);
        map.rotate(-rotv);
        map.scale(this.localScale.x,this.localScale.y);
        map.translate(-cntScreenPT.x, -cntScreenPT.y);
        map.beginPath();
        map.ellipse(p1.x, p1.y, disRadius, disRadius, 0, 0, Math.PI * 2, false);
        map.closePath();
        return 1;
    }

    //复制粘贴时，从复制源对象复制属性到本图形对应属性----虚函数，由实体继承类实现
    copySubPropFromBuf(bufInfo,tx,ty){
        this.copyCommnonPropFromBuf(bufInfo,tx,ty);
    }

    //检测point点是否落在当前图形对象的边界上
    chPtOnEdge(point,scaling){
        let flag = false;
        let dis = funcs.distancePoint(point,this._position,1);
        let deta = Math.abs(dis - this._position.radius)*scaling;
        if (deta < global.SelectGap){
            flag = true;
        }
        return flag;
    }
}

export default { CircleGraph }
